package com.rykj.energy.task.manage.schedule;

import com.rykj.energy.common.utils.CollectionUtils;
import com.rykj.energy.common.utils.DateUtils;
import com.rykj.energy.task.manage.vo.CycleTimeDto;
import com.rykj.energy.task.manage.vo.TriggerDto;
import io.swagger.annotations.ApiModelProperty;
import org.quartz.*;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Set;

import static org.quartz.DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TimeOfDay.hourMinuteAndSecondOfDay;

@Service("quartzService")
public class QuartzService implements IQuartzService {


    @Resource
    private Scheduler scheduler;

    @Override
    public void addJobSeconds(Class<? extends QuartzJobBean> jobClass, String jName, String jGroup, int seconds, JobDataMap jobDataMap) throws Exception {
        if(scheduler.checkExists(JobKey.jobKey(jName,jGroup))){
            deleteJob(jName,jGroup);
        }
        // 1. 创建一个JodDetail实例 将该实例与FieldTaskJob.class绑定 (链式写法)
        JobDetail jobDetail = newJob(jobClass) // 定义Job类为FieldTaskJob类，这是真正的执行逻辑所在
                .withIdentity(jName,jGroup) // 定义name/group
                .usingJobData(jobDataMap)
                .build();
        // 触发器
        Trigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity(jName + "_trigger",jGroup + "_TriggerGroup")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(seconds).repeatForever())
                .startAt(DateUtils.addHowSecond(new Date(),seconds))
                .build();

        scheduler.scheduleJob(jobDetail,trigger);
        // 启动
        if (!scheduler.isShutdown()){
            scheduler.start();
        }
    }

    @Override
    public void addJobCron(Class<? extends QuartzJobBean> jobClass, String jName, String jGroup, String cron, JobDataMap jobDataMap) throws Exception {
        if(scheduler.checkExists(JobKey.jobKey(jName,jGroup))){
            deleteJob(jName,jGroup);
        }
        // 1. 创建一个JodDetail实例 将该实例与FieldTaskJob.class绑定 (链式写法)
        JobDetail jobDetail = newJob(jobClass) // 定义Job类为FieldTaskJob类，这是真正的执行逻辑所在
                .withIdentity(jName,jGroup) // 定义name/group
                .usingJobData(jobDataMap)
                .build();
        // 触发器
        Trigger trigger = TriggerBuilder
                .newTrigger()
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .build();

        scheduler.scheduleJob(jobDetail,trigger);
        // 启动
        if (!scheduler.isShutdown()){
            scheduler.start();
        }
    }

    @Override
    public void addTermSecondsJob(Class<? extends QuartzJobBean> jobClass, String jName, String jGroup, int seconds, TriggerDto triggerDto, JobDataMap jobDataMap) throws Exception {

        if(triggerDto==null || CollectionUtils.isEmpty(triggerDto.getCycleTimes())
                || CollectionUtils.isEmpty(triggerDto.getWeeks())){
            throw new Exception("任务有效期或者周期不能为空！");
        }
        if(scheduler.checkExists(JobKey.jobKey(jName,jGroup))){
            deleteJob(jName,jGroup);
        }

        JobDetail jobDetail = newJob(jobClass) // 定义Job类为FieldTaskJob类，这是真正的执行逻辑所在
                .withIdentity(jName,jGroup) // 定义name/group
                .usingJobData(jobDataMap)
                .build();

        List<CycleTimeDto> cycleTimes = triggerDto.getCycleTimes(); //任务有效期
        Set<Integer> weeks = triggerDto.getWeeks(); //任务执行星期

        if(cycleTimes!=null && cycleTimes.size()>0){
            //设置任务有效期
            for(int i=0;i<cycleTimes.size();i++){
                CycleTimeDto cycleTimeDto = cycleTimes.get(i);
                DailyTimeIntervalScheduleBuilder scheduleBuilder = dailyTimeIntervalSchedule().withIntervalInSeconds(seconds);
                scheduleBuilder.startingDailyAt(hourMinuteAndSecondOfDay(cycleTimeDto.getStartHour(),cycleTimeDto.getStartMinute(),cycleTimeDto.getStartSeconds()))
                               .endingDailyAt(hourMinuteAndSecondOfDay(cycleTimeDto.getEndHour(),cycleTimeDto.getEndMinute(),cycleTimeDto.getEndSeconds()));

                if(triggerDto.getWeeks()!=null&&triggerDto.getWeeks().size()>0){
                    scheduleBuilder.onDaysOfTheWeek(triggerDto.getWeeks());
                }
                Trigger trigger = TriggerBuilder
                        .newTrigger()
                        .withIdentity(jName + "_" + i + "_trigger",jGroup + "_TriggerGroup")
                        .withSchedule(scheduleBuilder)
                        .forJob(jobDetail)
                        .build();

                if(i==0){
                    scheduler.scheduleJob(jobDetail,trigger);
                }else{
                    scheduler.scheduleJob(trigger);
                }
            }
        }else if(weeks !=null && weeks.size()>0){ //任务无有效期，只有星期
            //设置星期执行
            DailyTimeIntervalScheduleBuilder scheduleBuilder = dailyTimeIntervalSchedule()
                    .onDaysOfTheWeek(weeks)
                    .withIntervalInSeconds(seconds);

            Trigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(jName  + "_trigger",jGroup + "_TriggerGroup")
                    .withSchedule(scheduleBuilder)
                    .forJob(jobDetail)
                    .build();
            scheduler.scheduleJob(jobDetail,trigger);
        }
    }

    @Override
    public void pauseJob(String jName, String jGroup) throws SchedulerException {
        scheduler.pauseJob(JobKey.jobKey(jName, jGroup));
    }

    @Override
    public void resumeJob(String jName, String jGroup) throws SchedulerException {
        scheduler.resumeJob(JobKey.jobKey(jName, jGroup));
    }

    @Override
    public void deleteJob(String jName, String jGroup) throws SchedulerException {
        JobKey jobKey = new JobKey(jName,jGroup);
        scheduler.pauseJob(jobKey);
        scheduler.deleteJob(jobKey);// 删除任务
    }

}
